public interface TimeService { public String getTime(); }
In contrast to Gin, the Errai IOC container does not provide a programmatic way of creating and configuring injectors. Instead, container-level binding rules are defined by implementing a Provider, which is scanned for and auto-discovered by the container.
A Provider is essentially a factory which produces type instances within in the container, and defers instantiation responsibility for the provided type to the provider implementation. Top-level providers use the standard javax.inject.Provider<T> interface.
Types made available as top-level providers will be available for injection in any managed component within the container.
Out of the box, Errai IOC implements these default top-level providers, all defined in the org.jboss.errai.ioc.client.api.builtin package:
CallerProvider : Makes RPC Caller<T> objects available for injection.
DisposerProvider : Makes Errai IoC Disposer<T> objects available for injection.
InitBallotProvider : Makes instances of InitBallot available for injection.
IOCBeanManagerProvider : Makes Errai's client-side bean manager, ClientBeanManager, available for injection.
MessageBusProvider : Makes Errai's client-side MessageBus singleton available for injection.
RequestDispatcherProvider : Makes an instance of the RequestDispatcher available for injection.
RootPanelProvider : Makes GWT's RootPanel singleton injectable.
SenderProvider : Makes MessageBus Sender<T> objects available for injection.
Implementing a Provider is relatively straight-forward. Consider the following two classes:
TimeService.java
public interface TimeService { public String getTime(); }
TimeServiceProvider.java
@IOCProvider @Singleton public class TimeServiceProvider implements Provider<TimeService> { @Override public TimeService get() { return new TimeService() { public String getTime() { return "It's midnight somewhere!"; } }; } }
If you are familiar with Guice, this is semantically identical to configuring an injector like so:
Guice.createInjector(new AbstractModule() { public void configure() { bind(TimeService.class).toProvider(TimeServiceProvider.class); } }).getInstance(MyApp.class);
As shown in the above example code, the annotation @IOCProvider is used to denote top-level providers.
The classpath will be searched for all annotated providers at compile time.
Top-level providers are regular beans, so they can inject dependencies–particularly from other top-level providers–as necessary.